package dwei.astar
{
	import flash.display.BitmapData;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	
	public class AStarParserEight implements IAStarParser
	{
//============================================================================
//PROPERTY
//============================================================================
		private var _feeStraight:Number = 10;
		private var _feeOblique:Number = 14;
		
		private var _bm:BitmapData;
		private var _border:Number;
		private var _borderHalf:Number;
		private var _directs:Array;
		private var _rect:Rectangle;
//============================================================================
//CONSTRUCTOR
//============================================================================
		public function AStarParserEight(bm:BitmapData, border:Number = 16)
		{
			if (!bm) throw new Error("ParserAStarEight.bm不能为null");
			_bm = bm;
			_rect = new Rectangle(0, 0, bm.width, bm.height);
			_border = border;
			_borderHalf = _border >> 1;
			
			_directs = [
				new Point(1, 0), new Point(1, 1), new Point(0, 1), new Point(-1, 1), 
				new Point(-1, 0), new Point(-1, -1), new Point(0, -1), new Point(1, -1)
			];
		}
//============================================================================
//IMPLEMENTS
//============================================================================
		public function getVO(point:Point):AStarVO
		{
			if (!point) return null;
			return new AStarVO(Math.floor(point.x / _border), Math.floor(point.y / _border));
		}
		
		public function getPoint(vo:AStarVO):Point
		{
			if (!vo) return null;
			return new Point(vo.x * _border + _borderHalf, vo.y * _border + _borderHalf);
		}
		
		public function getArounds(vo:AStarVO):Array
		{
			var arounds:Array = [];
			var tempVO:AStarVO;
			var loopDirect:Point;
			var len:int = _directs.length;
			for (var index:int = 0;index < len;index++)
			{
				loopDirect = _directs[index];
				tempVO = new AStarVO(vo.x + loopDirect.x, vo.y + loopDirect.y);
				if (getMovable(tempVO)) arounds.push(tempVO);
			}
			return arounds;
		}
		
		public function getFeeFrom(voFrom:AStarVO, voTo:AStarVO):Number
		{
			if (!voFrom || !voTo || voFrom.equal(voTo)) return 0;
			if (!voFrom.isNeighbour(voTo)) return Number.MAX_VALUE;
			var disH:int = Math.abs(voTo.x - voFrom.x);
			var disV:int = Math.abs(voTo.y - voFrom.y);
			return (disH == 0 || disV == 0)?_feeStraight:_feeOblique;
		}
		
		public function getFeeTo(voFrom:AStarVO, voTo:AStarVO):Number
		{
			if (!voFrom || !voTo || voFrom.equal(voTo)) return 0;
			var disH:int = Math.abs(voTo.x - voFrom.x);
			var disV:int = Math.abs(voTo.y - voFrom.y);
			return (disH + disV) * _feeStraight;
		}
		
		public function getMovable(vo:AStarVO):Boolean
		{
			if (!vo) return false;
			var rectVO:Rectangle = new Rectangle(vo.x * _border, vo.y * _border, _border, _border);
			if (!_rect.containsRect(rectVO)) return false;
			var thumb:BitmapData = new BitmapData(_border, _border);
			thumb.copyPixels(bm, rectVO, new Point());
			if ((thumb.getPixel32(_borderHalf, _borderHalf) >> 24) == 0) return false;
			else return true;
		}
//============================================================================
//GETTER/SETTER
//============================================================================

		public function get bm():BitmapData
		{
			return _bm;
		}


	}
}